home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
gnumake
/
make360.zoo
/
function.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-07
|
30KB
|
1,187 lines
/* Variable function expansion for GNU Make.
Copyright (C) 1988, 1989 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GNU Make is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "variable.h"
#include "dep.h"
#include "commands.h"
#include "job.h"
#include <errno.h>
extern int errno;
static char *string_glob ();
/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is
the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is
nonzero, substitutions are done only on matches which are complete
whitespace-delimited words. If SUFFIX_ONLY is nonzero, substitutions are
done only at the ends of whitespace-delimited words. */
char *
subst_expand (o, text, subst, replace, slen, rlen, by_word, suffix_only)
char *o;
char *text;
char *subst, *replace;
unsigned int slen, rlen;
int by_word, suffix_only;
{
register char *t = text;
register char *p;
if (slen == 0 && !by_word && !suffix_only)
{
/* The first occurrence of "" in any string is its end. */
o = variable_buffer_output (o, t, strlen (t));
if (rlen > 0)
o = variable_buffer_output (o, replace, rlen);
return o;
}
while ((p = sindex (t, 0, subst, slen)) != 0)
{
/* Output everything before this occurrence of the string to replace. */
if (p > t)
o = variable_buffer_output (o, t, p - t);
/* If we're substituting only by fully matched words,
or only at the ends of words, check that this case qualifies. */
if ((by_word
&& ((p > t && p[-1] != ' ' && p[-1] != '\t')
|| (p[slen] != '\0' && p[slen] != ' ' && p[slen] != '\t'))
|| (suffix_only
&& (p[slen] != '\0' && p[slen] != ' ' && p[slen] != '\t'))))
/* Struck out. Output the rest of the string that is
no longer to be replaced. */
o = variable_buffer_output (o, subst, slen);
else if (rlen > 0)
/* Output the replacement string. */
o = variable_buffer_output (o, replace, rlen);
/* Advance T past the string to be replaced. */
t = p + slen;
}
/* Output everything left on the end. */
if (*t != '\0')
o = variable_buffer_output (o, t, strlen (t));
return o;
}
/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
and replacing strings matching PATTERN with REPLACE.
If PATTERN_PERCENT is not nil, PATTERN has already been
run through find_percent, and PATTERN_PERCENT is the result.
If REPLACE_PERCENT is not nil, REPLACE has already been
run through find_percent, and REPLACE_PERCENT is the result. */
char *
patsubst_expand (o, text, pattern, replace, pattern_percent, replace_percent)
char *o;
char *text;
register char *pattern, *replace;
register char *pattern_percent, *replace_percent;
{
register int pattern_prepercent_len, pattern_postpercent_len;
register int replace_prepercent_len, replace_postpercent_len;
register char *t;
unsigned int len;
int doneany = 0;
/* We call find_percent on REPLACE before checking PATTERN so that REPLACE
will be collapsed before we call subst_expand if PATTERN has no %. */
if (replace_percent == 0)
replace_percent = find_percent (replace);
if (replace_percent != 0)
{
/* Record the length of REPLACE before and after the % so
we don't have to compute these lengths more than once. */
replace_prepercent_len = replace_percent - replace;
replace_postpercent_len = strlen (replace_percent + 1);
}
else
/* We store the length of the replacement
so we only need to compute it once. */
replace_prepercent_len = strlen (replace);
if (pattern_percent == 0)
pattern_percent = find_percent (pattern);
if (pattern_percent == 0)
/* With no % in the pattern, this is just a simple substitution. */
return subst_expand (o, text, pattern, replace,
strlen (pattern), strlen (replace), 1, 0);
/* Record the length of PATTERN before and after the %
so we don't have to compute it more than once. */
pattern_prepercent_len = pattern_percent - pattern;
pattern_postpercent_len = strlen (pattern_percent + 1);
while (t = find_next_token (&text, &len))
{
int fail = 0;
/* Is it big enough to match? */
if (len < pattern_prepercent_len + pattern_postpercent_len)
fail = 1;
/* Does the prefix match? */
if (!fail && pattern_prepercent_len > 0
&& (*t != *pattern
|| t[pattern_prepercent_len - 1] != pattern_percent[-1]
|| strncmp (t + 1, pattern + 1, pattern_prepercent_len - 1)))
fail = 1;
/* Does the suffix match? */
if (!fail && pattern_postpercent_len > 0
&& (t[len - 1] != pattern_percent[pattern_postpercent_len]
|| t[len - pattern_postpercent_len] != pattern_percent[1]
|| strncmp (&t[len - pattern_postpercent_len],
&pattern_percent[1], pattern_postpercent_len - 1)))
fail = 1;
if (fail)
/* It didn't match. Output the string. */
o = variable_buffer_output (o, t, len);
else
{
/* It matched. Output the replacement. */
/* Output the part of the replacement before the %. */
o = variable_buffer_output (o, replace, replace_prepercent_len);
if (replace_percent != 0)
{
/* Output the part of the matched string that
matched the % in the pattern. */
o = variable_buffer_output (o, t + pattern_prepercent_len,
len - (pattern_prepercent_len
+ pattern_postpercent_len));
/* Output the part of the replacement after the %. */
o = variable_buffer_output (o, replace_percent + 1,
replace_postpercent_len);
}
}
/* Output a space, but not if the replacement is "". */
if (fail || replace_prepercent_len > 0
|| (replace_percent != 0 && len + replace_postpercent_len > 0))
{
o = variable_buffer_output (o, " ", 1);
doneany = 1;
}
}
if (doneany)
/* Kill the last space. */
--o;
return o;
}
/* Handle variable-expansion-time functions such as $(dir foo/bar) ==> foo/ */
/* These enumeration constants distinguish the
various expansion-time built-in functions. */
enum function
{
function_subst,
function_addsuffix,
function_addprefix,
function_dir,
function_notdir,
function_suffix,
function_basename,
function_wildcard,
function_firstword,
function_word,
function_words,
function_findstring,
function_strip,
function_join,
function_patsubst,
function_filter,
function_filter_out,
function_foreach,
function_sort,
function_origin,
function_shell,
function_invalid
};
/* Greater than the length of any function name. */
#define MAXFUNCTIONLEN 11
/* The function names and lengths of names, for looking them up. */
static struct
{
char *name;
unsigned int len;
enum function function;
} function_table[] =
{
{ "subst", 5, function_subst },
{ "addsuffix", 9, function_addsuffix },
{ "addprefix", 9, function_addprefix },
{ "dir", 3, function_dir },
{ "notdir", 6, function_notdir },
{ "suffix", 6, function_suffix },
{ "basename", 8, function_basename },
{ "wildcard", 8, function_wildcard },
{ "firstword", 9, function_firstword },
{ "word", 4, function_word },
{ "words", 5, function_words },
{ "findstring", 10, function_findstring },
{ "strip", 5, function_strip },
{ "join", 4, function_join },
{ "patsubst", 8, function_patsubst },
{ "filter",